#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <ADS1115_WE.h>
#include <Wire.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "esp_system.h"
#include "QuickPID.h"

//LED调光PWM
int ledcur = 4;
int ledset = 4;
int timeLedOn[2] = {18, 22}; //开启时间,关闭时间

//ADC采集
int debugMod = 0;
ADS1115_WE adc;
float adc_v[4] = {0.0};
float rr = 0.05;
float TMP = 20.01, PH = 7.02;

//网络
const char *host = "esp32";
const char *ssid = "无线路由器名";
const char *password = "无线路由器1密码";
WebServer server(80);
const char *serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
const char *mqtt_server = "183.230.40.39";
const char *DeviceID = "设备号";   //设备号
const char *ProductID = "产品号";  //产品号
const char *AuthInfo = "鉴权信息"; //鉴权信息去设备信息里添加
String data_stream_name_rw[10] = {"o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", "o8", "L0"};
int data_stream_value_rw[10] = {1, 1, 2, 2, 0, 0, 0, 0, 1, 0};
String data_stream_name_r1[3] = {"t", "ph", "power"};
float data_stream_value_r1[3] = {25.67, 8.35, 0.0};
String data_stream_name_r2[4] = {"i0", "i1", "i2", "i3"};
int data_stream_value_r2[4] = {0, 0, 0, 0};
WiFiClient espClient;
PubSubClient client(espClient);
int OTAtrig = 0;

//时间
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60 * 60 * 8, 30 * 60 * 1000);
uint32_t now_ms = 0;
int now_s = 0;
int h;

//GPIO
int GPO[9] = {23, 22, 21, 4, 15, 32, 33, 27, 2};
int GPI[4] = {13, 14, 34, 35};

//主泵和蛋分
int bumpdelay = 200;
int bumpOn = 0;
int curbumpdelay = 0;
int W_level[4] = {0, 0, 1, 0}; //污水高,底滤高,底滤低,补水低

//OLED
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//控温
int powerstart = 0; //启动延时计数
float Setpoint = 21;
float pidInput, pidOutput, pidOutput2, pidpowerOut;
//Specify the links and initial tuning parameters
float Kp = 2, Ki = 5, Kd = 1;
float POn = 1.0; // proportional on Error to Measurement ratio (0.0-1.0), default = 1.0
float DOn = 0.0; // derivative on Error to Measurement ratio (0.0-1.0), default = 0.0
QuickPID myQuickPID(&pidInput, &pidOutput, &Setpoint, Kp, Ki, Kd, POn, DOn, QuickPID::DIRECT);
unsigned int WindowSize = 10000;
unsigned int minWindow = 500;
unsigned long windowStartTime;

//造浪
int Wave1On[2] = {8, 18}; //开启时间,关闭时间
int Wave2On[2] = {6, 22}; //开启时间,关闭时间

void setup()
{
    // put your setup code here, to run once:
    Serial.begin(115200);
    Serial.println("start!");
    led_init();
    ctl_init();
    Wire.begin(19, 18, 400000);
    Wire1.begin(26, 25, 400000);
    delay(100);
    dispInit();
    adc = ADS1115_WE(&Wire1, 0x48);
    // pinMode(12, INPUT);

    if (!adc.init())
    {
        Serial.println("ADS1115 not connected!");
    }
    adc.setVoltageRange_mV(ADS1115_RANGE_6144);
    adc.setCompareChannels(ADS1115_COMP_0_GND);
    adc.setConvRate(ADS1115_250_SPS);
    adc.setMeasureMode(ADS1115_CONTINUOUS);

    // Connect to WiFi network
    WiFi.begin(ssid, password);
    Serial.println("");

    // Wait for connection
    int wifiWait = 40;
    while (WiFi.status() != WL_CONNECTED && wifiWait > 0)
    {
        wifiWait--;
        delay(500);
        Serial.print(".");
        if (wifiWait == 0)
        {
            Serial.println("");
            Serial.println("wifi not connect");
        }
    }
    Serial.println("");

    display.clearDisplay();
    display.setTextSize(1);      // Normal 1:1 pixel scale
    display.setTextColor(WHITE); // Draw white text
    display.setCursor(0, 0);
    display.println("onenet connecting");
    display.display();

    client.setServer(mqtt_server, 6002);
    client.setCallback(callback);
    reconnect();

    timeClient.begin();
}

void loop()
{
    // put your main code here, to run repeatedly:

    //  if (digitalRead(12) == 1)
    //  {
    //      OTAtrig = 1;
    // }
    if (OTAtrig == 1)
    {
        webOTA();
    }
    // if the LED is off turn it on and vice-versa:
    if (client.connected())
    {
        client.loop();
    }
    if (millis() - now_ms > 100)
    {
        now_ms = millis();
        per_01sec();
    }
}
